<template>
    <div id="container">
        <div ref="cvsBox" id="tree" :style="height ?  `height:${height}px;` : 'height:100%'">
            <canvas ref="cvs"></canvas>
        </div>
    </div>

    <template>
        <a-image v-for="(item,index) in data.children" :width="200" :style="{ display: 'none' }" :preview="{
            visible:item.visible,
            onVisibleChange: ()=> emits('changeVisible',`child${index + 1}`)
        }" :src="item.src" />
    </template>
</template>
<script lang='ts' setup>
import { debounce } from 'lodash';
import { nextTick, inject,ref, watch } from 'vue';
import { Circle,ImgRegion, Text } from '@/utils/CanvasNode';

interface props{
    height:number,
    mode:string
    data:node
}

interface node{
    title?: string,
    describe?:string
    type?: string,
    imageType?: string,
    src?: string,
    size?: number,
    children?: node[],
    visible?:boolean,
    onChange?:Function
}

const emits = defineEmits(['changeVisible'])


const props = defineProps<props>()
const cvsBox = ref()
const cvs = ref()

let ctx:CanvasRenderingContext2D,w:number,nodeObj:any = {}

const color = '#000'
const fontFamily = '黑体'
const fontSize = 16

watch(
    ()=>props.data,
    (newval,olval)=>{
        if(newval !== olval){
            initCvs()
        }
    },
    {deep:true}
)




initCvs()
window.onresize = debounce(()=>initCvs(),1000)
async function initCvs(){
    await nextTick()
    w = cvsBox.value.clientWidth
    const canvas = cvs.value as HTMLCanvasElement

    canvas.width = w
    canvas.height = props.height
    ctx = canvas.getContext('2d')!

    handlerData()

    handlerClickCVS()
}

function handlerData(){
    const {children,...data} = props.data

    drawParent(data)
    if(children){
        const joint = w / (children.length + 1)
        children.forEach((item,index) => {
            nodeObj[`child${index + 1}`] = new ImgRegion().create(ctx, joint * (index + 1) - item.size! / 2, 200, item.size!, item.size!, item.src!)
            nodeObj[`childText${index + 1}`] = new Text().create(ctx, color, fontSize, fontFamily, joint * (index + 1) - item.size! / 2, 200 + item.size! + fontSize, item.size!, item.title!)
            // nodeObj[`childText${index + 1}`] = new Text().create(ctx, color, fontSize - 2, fontFamily, joint * (index + 1) - item.size! / 2, 200 + item.size! + fontSize *2, item.size!, item.describe!)
        })
    }
    drawLine()
}
function drawParent(item: node){
    let left: number, top: number
    const { title, type, imageType, src, size } = item
    if(props.mode === 'top' && size && src && type === 'img'){
        left = w / 2 - size / 2
        top = 20
        const textNode = new Text().create(ctx,color,fontSize + 4, fontFamily, left, fontSize,size, title!)
        const circleNode = new Circle().create(ctx, left, top, size)
        const imgNode = new ImgRegion().create(ctx,left,top,size,size,src)

        nodeObj.circleNode = circleNode
        nodeObj.imgNode = imgNode
        nodeObj.textNode = textNode
    }
}

function drawLine(){
    const { BottomCenter: circleCenter } = nodeObj.circleNode.getCenterOffset()
    const { TopCenter: childCenter1 } = nodeObj.child1.getCenterOffset()
    const { TopCenter: childCenter2 } = nodeObj.child2.getCenterOffset()

    ctx.beginPath();
    ctx.moveTo(circleCenter.x, circleCenter.y);
    ctx.bezierCurveTo(circleCenter.x , circleCenter.y+50 , childCenter1.x , childCenter1.y -50, childCenter1.x, childCenter1.y);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(circleCenter.x, circleCenter.y);
    ctx.bezierCurveTo(circleCenter.x  , circleCenter.y+50, childCenter2.x, childCenter2.y-50 , childCenter2.x, childCenter2.y);
    ctx.stroke();
}

function handlerClickCVS(){
    const {child1,child2} = nodeObj

    const { TopLeft:TL1, BottomRight:BR1 } = child1.getClientOffset()
    const {TopLeft:TL2,BottomRight:BR2} = child2.getClientOffset()

    const chil1Pos = {
        startX:TL1.x,
        startY:TL1.y,
        endX:BR1.x,
        endY:BR1.y
    }
    const chil2Pos = {
        startX: TL2.x,
        startY: TL2.y,
        endX: BR2.x,
        endY: BR2.y
    }
    cvs.value.addEventListener('mousemove', function (e: MouseEvent) {
        const clickX = e.offsetX
        const clickY = e.offsetY

        if (clickX >= chil1Pos.startX && clickX <= chil1Pos.endX && clickY >= chil1Pos.startY && clickY <= chil1Pos.endY) {
            cvs.value.style.cursor = 'pointer'
        }else if (clickX >= chil2Pos.startX && clickX <= chil2Pos.endX && clickY >= chil2Pos.startY && clickY <= chil2Pos.endY) {
            cvs.value.style.cursor = 'pointer'
        } else {
            cvs.value.style.cursor = 'auto'
        }
    })

    cvs.value.onclick = function (e:MouseEvent) {
        // console.log(e);
        
        const clickX = e.offsetX
        const clickY = e.offsetY

        if(clickX >= chil1Pos.startX && clickX <= chil1Pos.endX && clickY >= chil1Pos.startY && clickY <= chil1Pos.endY){
            // console.log('click child1');
            emits('changeVisible','child1')
            
        }
        if(clickX >= chil2Pos.startX && clickX <= chil2Pos.endX && clickY >= chil2Pos.startY && clickY <= chil2Pos.endY){
            // console.log('click child2');
            emits('changeVisible','child2')
        }
    }
}

function setVisible(visible:boolean){
    visible = !visible
}
    
</script>
<style lang='scss' scoped>
    #container{
        padding: 12px;
    }
</style>